package com.zhongbo.java.websocket.web.websocket;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zhongbo.java.websocket.model.ChatHistory;
import com.zhongbo.java.websocket.model.User;
import com.zhongbo.java.websocket.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 说明：
 *
 * @author 钟波dellNotebook
 * @since 2025年03月18日 星期二 10:02:54
 */
@ServerEndpoint(value = "/chat/{userId}")
@Component
@Slf4j
public class Chat1WebSocket {
    // session缓存
  public final static Map<String, Session> sessionMap = new HashMap<>();

  private static IChatHistoryService chatHistoryService;
  private static IRedisOnlineService redisOnlineService;
  private static IUserService userService;
  // 消息排行榜服务
  private static IMessageRankService messageRankService;
  private static RedisMessagePublisher redisMessagePublisher;

    /**
     * 自动注入依赖的spring bean
     */
  @Autowired
  public void setServices(
          IChatHistoryService chatHistoryService,
          IRedisOnlineService redisOnlineService,
          IUserService userService,
          IMessageRankService messageRankService,
          RedisMessagePublisher redisMessagePublisher
  ){
      Chat1WebSocket.chatHistoryService = chatHistoryService;
      Chat1WebSocket.redisOnlineService = redisOnlineService;
      Chat1WebSocket.userService = userService;
      Chat1WebSocket.messageRankService = messageRankService;
      Chat1WebSocket.redisMessagePublisher = redisMessagePublisher;
  }

    public Chat1WebSocket() {
        System.out.println("载入 Chat1WebSocket 构造方法");
    }

    @OnOpen
    public void openConn(Session session, @PathParam("userId")String userId) {
        String sessionId = session.getId();
        System.out.println("建立ws连接: " + sessionId);
        // 判断用户是否合法
        User detail = userService.detail(userId);
        if(detail == null){
            doClose(session,"用户id不存在, 拒绝连接");
            return;
        }
        // redis记录在线用户
        redisOnlineService.loginUser(userId);
        sessionMap.put(sessionId, session);
    }

    /**
     * 向ws chat客户端发送错误消息,并且断开连接
     * @param session session会话
     * @param msg 错误消息
     */
    private void doClose(Session session, String msg) {
        try {
            if (StrUtil.isNotBlank(msg)) {
                sendMessage(session,msg);
            }
            session.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 发送文本消息
     *
     * @param session ws会话对象
     * @param msg     消息文本
     */
    private void sendMessage(Session session, String msg) {
        try {
            session.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            log.error("给 ws 客户端: {} 发送消息失败", session.getId(), e);
        }
    }

    @OnClose
    public void onClose(Session session, CloseReason reason) {
        String sessionId = session.getId();
        String reasonPhrase = reason.getReasonPhrase();
        System.out.println(String.format("关闭ws连接: %s, reason: %s", sessionId, reasonPhrase));
        sessionMap.remove(sessionId);
    }

    @OnMessage
    public void echoTextMessage(Session session, String msg, boolean last, @PathParam("userId") String userId) {
        if (session.isOpen()) {
            System.out.println("收到ws消息 = " + msg);
            // 记录消息排行信息
            messageRankService.addMessageCount(userId);

            // 广播消息到redis channel
            redisMessagePublisher.publishMessage(msg);

            /* 通过redis订阅后, 原有广播消息不需要了 */
            // // 给所有ws客户端广播消息
            // sessionMap.values().forEach(otherSession -> {
            //     try {
            //         otherSession.getBasicRemote().sendText(msg);
            //     } catch (IOException e) {
            //         System.out.println("广播消息发生异常: "+e.getMessage());
            //     }
            // });

            // 解析用户发送过来的json格式消息内容
            // 如果用户发送了非json数据,会导致异常.
            try {
                JSONObject jsonObject = JSONUtil.parseObj(msg);
                ChatHistory chatHistory = jsonObject.toBean(ChatHistory.class);
                chatHistoryService.add(chatHistory);
            }catch (Exception e){
                //
                System.err.println("解析json格式异常, json:"+msg);
            }


        }
    }
    /*
    html 客户端代码:
    var wsClient = new WebSocket('ws://localhost:8080/chat1/zhangsan/99999')
    wsClient.send('你好吗?')
    wsClient.close()
     */

}
